package com.siebre.demo.jdbc.queue;

import java.util.Map;

import org.springframework.jdbc.core.ColumnMapRowMapper;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SingleColumnRowMapper;

/**
 * 
 * @author ZhangChi
 * @since 2015年2月1日
 */
public class JdbcQueueBuilderFactory {
	
	private final JdbcOperations jdbcOps;
	
	public JdbcQueueBuilderFactory(JdbcOperations jdbcOps) {
		this.jdbcOps = jdbcOps;
	}
	
	public JdbcQueueBuilder<Map<String, Object>> backedBySql(String selectSql) {
		return new JdbcQueueBuilder<Map<String, Object>>(selectSql, new ColumnMapRowMapper());
	}
	
	public <T> JdbcQueueBuilder<T> backedBySql(String selectSql, RowMapper<T> rowMapper) {
		return new JdbcQueueBuilder<T>(selectSql, rowMapper);
	}
	
	public <T> JdbcQueueGenerator<T> fromTable(String tableName) {
		return new JdbcQueueGenerator<T>(tableName);
	}

	public class JdbcQueueGenerator<T> {
		
		private final String tableName;
		
		private String keyColumn;
		
		private Class<T> keyType;
		
		private String statusColumn;
		
		private Object initialStatus;
		
		private Object fetchedStatus;
		
		JdbcQueueGenerator(String tableName) {
			this.tableName = tableName;
		}

		public JdbcQueueGenerator<T> withKey(String columnName, Class<T> columnType) {
			keyColumn = columnName;
			keyType = columnType;
			return this;
		}
		
		public JdbcQueueGenerator<T> withStatus(String columnName, Object initialStatus, Object fetchedStatus) {
			statusColumn = columnName;
			this.initialStatus = initialStatus;
			this.fetchedStatus = fetchedStatus;
			
			return this;
		}
		
		public JdbcQueue<T> build() {
			String selectSql = String.format("select %s from %s where %s=? order by %s", keyColumn, tableName, statusColumn, keyColumn);
			String updateSql = String.format("update %s set %s=? where %s=? and %s=?", tableName, statusColumn, keyColumn, statusColumn);
			return new JdbcQueue<T>(jdbcOps, selectSql, new SingleColumnRowMapper<T>(keyType), updateSql);
		}
	}
	
	public class JdbcQueueBuilder<T> {

		private String selectSql;
		
		private RowMapper<T> rowMapper;
		
		private String updateSql;
		
		private JdbcQueueBuilder(String selectSql, RowMapper<T> rowMapper) {
			this.selectSql = selectSql;
			this.rowMapper = rowMapper;
		}
		
		public JdbcQueueBuilder<T> fetchBy(String updateSql) {
			this.updateSql = updateSql;
			return this;
		}

		public JdbcQueue<T> build() {
			return new JdbcQueue<T>(jdbcOps, selectSql, rowMapper, updateSql);
		}
	}
}
